from pydantic import BaseModel, Field, model_validator
from typing import Union, List
from fastapi import UploadFile
import json
import hashlib
from app.api.schemas.languages import Lang


class _BasePayload(BaseModel):
    """
    翻译请求的基本信息。
    """

    from_lang: str = Field(None, title="源语言", description="源语言的代码。")
    to_lang: str = Field(..., title="目标语言", description="目标语言的代码。")


class TextTransPayload(_BasePayload):
    """
    文本翻译请求体。
    """

    text: str = Field(..., title="文本", description="待翻译的文本。")


class FileTransPayload(_BasePayload):
    """
    文档翻译请求体。
    """

    url: Union[str, None] = Field(None, title="URL", description="待翻译的文件的 URL。")
    file: Union[UploadFile, None] = Field(
        None, title="文件", description="待翻译的文件。"
    )

    @model_validator(mode="before")
    def check_url_or_file(cls, values):
        """
        自定义验证方法，确保 `url` 和 `file` 至少提供一个。
        """
        if not values.get("url") and not values.get("file"):
            raise ValueError("url 和 file 至少需要提供一个。")
        return values


class TextTransResult(BaseModel):
    """
    翻译实体类
    """

    src: str
    from_lang: Lang
    to_lang: Lang
    dst: Union[str, None] = None

    def set_result(self, dst):
        self.dst = dst

    def __repr__(self):
        """
        重写 __repr__ 方法，返回 JSON 字符串
        """
        return json.dumps(
            self, default=self._custom_encoder, ensure_ascii=False, indent=4
        )

    def _custom_encoder(self, obj):
        if isinstance(obj, Lang):
            return obj.name
        return obj.__dict__


class FragmentTransResultDict(dict):
    """翻译结果字典，用于存储分片翻译结果"""

    def __init__(self):
        super().__init__()

    def add_enity(self, entity: TextTransResult):
        """添加翻译实体"""
        key = hashlib.md5(f"{entity.src}.{entity.to_lang}".encode("utf-8")).hexdigest()
        self[key] = entity

    def add_entity_from_details(self, src: str, from_lang: Lang, to_lang: Lang):
        """添加翻译实体"""
        entity = TextTransResult(src=src, from_lang=from_lang, to_lang=to_lang)
        self.add_enity(entity)

    def get_entity(self, e_tag: str):
        """获取翻译实体"""
        return self.get(e_tag) if e_tag in self else None

    def get_entity_by_src(self, src: str, to_lang: Lang):
        """获取翻译实体"""
        e_tag = hashlib.md5(f"{src}.{to_lang}".encode("utf-8")).hexdigest()
        return self.get_entity(e_tag)


class _BaseResponse(BaseModel):
    """
    翻译结果的基本信息。
    """

    errno: int = Field(..., title="错误码", description="错误码，0 表示成功。")
    msg: str = Field(..., title="消息", description="消息，通常为 'ok'。")


class TextTransResponse(_BaseResponse):
    """
    文本翻译结果。
    """

    result: TextTransResult = Field(..., title="结果", description="翻译结果。")


class FileTransResponse(_BaseResponse):
    """
    文件翻译结果。
    """

    class _TransResultItem(BaseModel):
        """
        单个翻译文件结果项。
        """

        id: str = Field(..., title="ID", description="翻译文件ID。")
        name: str = Field(..., title="名称", description="翻译文件名称。")
        status: str = Field(..., title="状态", description="翻译文件状态。")
        url: str = Field(None, title="URL", description="翻译后的文件的 URL。")

    task_id: str = Field(..., title="任务ID", description="翻译任务的 ID。")
    procss: int = Field(..., title="进度", description="翻译进度。")
    data: List[_TransResultItem] = Field(
        ..., title="数据", description="翻译结果列表。"
    )
